package com.find.securityswagger.auth;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * @Author 江南一点雨
 * @Site www.javaboy.org 2019-08-11 17:38
 */
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
    /**
     * @param authentication 当前用户具备的角色
     * @param o
     * @param collection     当前路径需要的角色，这里是在MyFiter处理后得到的
     * @throws AccessDeniedException
     * @throws InsufficientAuthenticationException
     */
    @Override
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        for (ConfigAttribute attribute : collection) {
            if ("ROLE_login".equals(attribute.getAttribute())) {
                // 如果是返回的ROLE_login说明你请求的路径不存在，所有判断你有没有登录 登录的就直接放行
                if (authentication instanceof AnonymousAuthenticationToken) {
                    throw new AccessDeniedException("非法请求!");
                } else {
                    return;
                }
            }
            // 获取我具备的角色
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            // 做匹配
            for (GrantedAuthority authority : authorities) {
                if (authority.getAuthority().equals(attribute.getAttribute())) {
                    return;
                }
            }
        }
        // 例如，我具备某些角色，但是此角色没有此路径的权限，那就是非要请求
        throw new AccessDeniedException("非法请求!");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}